package com.lanjiu.lib.utils.file;

import android.text.TextUtils;

import com.google.protobuf.ByteString;
import com.lanjiu.lib.utils.th.Threader;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.UUID;

/**
 * @description: 文件操作工具类
 * @author: Panwei
 * @date: 2019/11/1 15:55
 */
public class FileOperator {

    private FileOperator() {
    }

    /**
     * 检查文件目录
     *
     * @param directory 文件目录
     */
    public static boolean mkDirectory(String directory) {
        File mFolder = new File(directory);
        if (mFolder.exists()) {
            if (!mFolder.isDirectory()) {
                if (mFolder.delete()) {
                    return mFolder.mkdirs();
                }
                return false;
            }
            return true;
        } else {
            return mFolder.mkdirs();
        }
    }

    public static boolean mkDirectory(File mFolder) {
        if (mFolder.exists()) {
            if (!mFolder.isDirectory()) {
                if (mFolder.delete()) {
                    return mFolder.mkdirs();
                }
                return false;
            }
            return true;
        } else {
            return mFolder.mkdirs();
        }
    }

    public static boolean delete(String filePath) {
        return new File(filePath).delete();
    }

    public static boolean delete(File file) {
        return file.delete();
    }

    /**
     * 删除单个文件
     *
     * @param file 被删除文件的文件名
     * @return 文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String file) {
        File ioFile = new File(file);
        if (ioFile.isFile() && ioFile.exists()) {
            return ioFile.delete();
        }
        return false;
    }

    /**
     * 删除文件夹以及目录下的文件
     *
     * @param directory   被删除目录的文件路径
     * @param isDeleteDir 是否删除根目录
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String directory, boolean isDeleteDir) {
        //如果filePath不以文件分隔符结尾，自动添加文件分隔符
        if (!directory.endsWith(File.separator) && directory.endsWith("/")) {
            directory += File.separator;
        }
        File dirFile = new File(directory);
        if (!dirFile.exists()) return false;
        if (!dirFile.isDirectory()) {
            if (isDeleteDir)
                return dirFile.delete();
            return false;
        }

        boolean flag = false;
        File[] files = dirFile.listFiles();
        //遍历删除文件夹下的所有文件(包括子目录)
        if (files != null) {
            for (File file : files) {
                if (file.isFile()) {
                    //删除子文件
                    flag = deleteFile(file.getAbsolutePath());
                    if (!flag) break;
                } else {
                    //删除子目录
                    flag = deleteDirectory(file.getAbsolutePath(), true);
                    if (!flag) break;
                }
            }
        }
        if (flag && isDeleteDir)
            return dirFile.delete();
        return flag;
    }

    /**
     * 获取文件后缀名
     *
     * @param file 文件路径或文件名
     * @return
     */
    public static String getSuffixName(String file) {
        int index = file.lastIndexOf(".");
        if (index >= 0)
            return file.substring(file.lastIndexOf("."));
        else
            return "";
    }

    /**
     * 获取文件名
     *
     * @param file     文件路径
     * @param isSuffix 是否带后缀名
     * @return
     */
    public static String getFileName(String file, boolean isSuffix) {
        String fileName = "";
        int index = file.lastIndexOf("/");
        if (index == -1)
            index = file.lastIndexOf("\\");
        if (index >= 0)
            fileName = file.substring(index + 1);

        if (!isSuffix) {
            int position = fileName.lastIndexOf(".");
            if (position >= 0)
                fileName = fileName.substring(0, position);
        }
        return fileName;
    }

    /**
     * 随机文件名
     *
     * @return
     */
    public static String randomFileName() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 保存文件(随机文件名)
     *
     * @param folder 保存文件夹
     * @param buffer 文件buffer
     * @return
     */
    public static String saveFile(String folder, ByteBuffer buffer) {
        if (TextUtils.isEmpty(folder)) return null;
        String fileName = randomFileName();
        File file;
        while ((file = new File(folder, fileName)).exists()) {
            fileName = randomFileName();
        }
        try {
            RandomAccessFile write = new RandomAccessFile(file, "rw");
            FileChannel writeChannel = write.getChannel();
            writeChannel.write(buffer);
            writeChannel.close();
            writeChannel = null;
            write.close();
            write = null;
            return file.getAbsolutePath();
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 保存文件
     *
     * @param folder   保存文件夹
     * @param fileName 文件名
     * @param buffer   文件buffer
     * @return
     */
    public static String saveFile(String folder, String fileName, ByteBuffer buffer) {
        if (TextUtils.isEmpty(folder) || TextUtils.isEmpty(fileName)) return null;
        File file;
        String fileTempName = fileName;
        int index = 0;
        while ((file = new File(folder, fileTempName)).exists()) {
            fileTempName = fileName + "(" + (++index) + ")";
        }
        try {
            RandomAccessFile write = new RandomAccessFile(file, "rw");
            FileChannel writeChannel = write.getChannel();
            writeChannel.write(buffer);
            writeChannel.close();
            writeChannel = null;
            write.close();
            write = null;
            return file.getAbsolutePath();
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 异步保存文件(随机文件名)
     *
     * @param folder   保存文件夹
     * @param buffer   文件buffer
     * @param listener 文件保存监听
     * @return
     */
    public static void execSaveFile(String folder, ByteBuffer buffer, OnFileSavedListener listener) {
        Threader.run(() -> {
            String filePath = saveFile(folder, buffer);
            if (listener != null)
                listener.onFileSaved(!TextUtils.isEmpty(filePath), filePath);
        });
    }

    /**
     * 异步保存文件
     *
     * @param folder   保存文件夹
     * @param fileName 文件名
     * @param buffer   文件buffer
     * @param listener 文件保存监听
     * @return
     */
    public static void execSaveFile(String folder, String fileName, ByteBuffer buffer, OnFileSavedListener listener) {
        Threader.run(() -> {
            String filePath = saveFile(folder, fileName, buffer);
            if (listener != null)
                listener.onFileSaved(!TextUtils.isEmpty(filePath), filePath);
        });
    }

    /**
     * 读取文件
     *
     * @param path 文件地址
     * @return
     */
    public static ByteString readFile(String path) {
        RandomAccessFile read = null;
        FileChannel readChannel = null;
        try {
            read = new RandomAccessFile(path, "r");
            readChannel = read.getChannel();
            return ByteString.copyFrom(readChannel.map(FileChannel.MapMode.READ_ONLY, 0, read.length()));
        } catch (IOException e) {
            return null;
        } finally {
            try {
                if (null != readChannel)
                    readChannel.close();
                if (null != read)
                    read.close();
            } catch (IOException e) {
            }
        }
    }

    /**
     * 异步读取文件
     *
     * @param path     文件地址
     * @param listener 文件读取监听
     * @return
     */
    public static void execReadFile(String path, OnFileReadListener listener) {
        Threader.run(() -> {
            ByteString byteString = readFile(path);
            if (null != listener)
                listener.onFileRead(byteString != null, byteString);
        });
    }

    public interface OnFileSavedListener {
        void onFileSaved(boolean isSucc, String filePath);
    }

    public interface OnFileReadListener {
        void onFileRead(boolean isSucc, ByteString byteString);
    }
}
